package org.common.utils.database.mapper;

import org.common.utils.function.BiConsumerThrows;
import org.common.utils.function.FunctionThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 数据操作抽象类
 * @author zhouzhibing
 * @date 2025/1/9
 */
public abstract class AbstractMapper<T> {
    private static final Logger log = LoggerFactory.getLogger(AbstractMapper.class);

    /**
     * 执行查询
     * @param whereString 条件sql
     * @param params 条件参数列表
     * @return 对应泛型的列表
     */
    public abstract List<T> select(String whereString , List<Object> params);

    /**
     * 执行插入
     * @param object 对象
     * @return 是否成功
     */
    public abstract int insert(T object);

    /**
     * 执行插入
     * @param list 对象列表
     * @return 是否成功
     */
    public abstract int[] insert(List<T> list);

    /**
     * 执行更新
     * @param object 对象
     * @return 是否成功
     */
    public abstract int update(T object);

    /**
     * 执行更新
     * @param list 对象列表
     * @return 是否成功
     */
    public abstract int[] update(List<T> list);

    /**
     * 执行删除
     * @param object 对象
     * @return 是否成功
     */
    public abstract int delete(T object);

    /**
     * 执行删除
     * @param list 对象列表
     * @return 是否成功
     */
    public abstract int[] delete(List<T> list);

    /**
     * @return 获取连接
     */
    protected Connection getConnection() {
        try {
            return MapperManager.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 执行批量操作
     * @param sqlTemplate sql语句模板
     * @param list 实例列表
     * @param consumer 参数操作
     * @return 批量操作结果
     */
    protected int [] executeBatch(String sqlTemplate , List<T> list , BiConsumerThrows<PreparedStatement , T> consumer) {
        try(Connection connection = getConnection()) {
            PreparedStatement statement = connection.prepareStatement(sqlTemplate);
            for (T instance : list) {
                consumer.accept(statement , instance);
                statement.addBatch();
            }
            return statement.executeBatch();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *  执行查询
     * @param sqlTemplate sql语句模板
     * @param whereString 条件sql
     * @param params 条件sql参数列表
     * @param function 返回对应查询的列表
     * @return 对应泛型的列表
     */
    protected List<T> executeList(String sqlTemplate , String whereString , List<Object> params , FunctionThrows<ResultSet , T> function) {
        try(Connection connection = getConnection()) {
            PreparedStatement statement = connection.prepareStatement(sqlTemplate + whereString , ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            if(params != null) {
                for (int i = 0; i < params.size(); i++) {
                    statement.setObject(i + 1 , params.get(i));
                }
            }
            ResultSet resultSet = statement.executeQuery();
            resultSet.last();
            int size = resultSet.getRow();
            List<T> list = new ArrayList<>(size);
            resultSet.beforeFirst();

            while (resultSet.next()) {
                T instance = function.apply(resultSet);
                list.add(instance);
            }
            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
